﻿using System;
using Reactor.Messaging.ServiceBus;

namespace Reactor.Messaging
{
    /// <summary>
    /// Context delivered with a message that allows contact to the bus that delivered the message and 
    /// allows acknowledgement of the message or replies to request type messages.
    /// </summary>
    public interface IMessageContext
    {
        /// <summary>
        /// Gets or sets the bus this message was delivered from.
        /// </summary>
        /// <value>The bus.</value>
        IServiceBus Bus { get; set; }

        /// <summary>
        /// Gets or sets the number of times the message has been attempted to be delivered.
        /// </summary>
        /// <value>The number of delivery attempts.</value>
        int NumberOfDeliveryAttempts { get; set; }

        /// <summary>
        /// Gets or sets the raw message.
        /// </summary>
        /// <value>The raw message.</value>
        object RawMessage { get; set; }

        /// <summary>
        /// Gets or sets the id of the workflow instance orchestrating the business process the message is participating in.
        /// </summary>
        /// <value>The workflow instance id.</value>
        Guid WorkflowInstanceId { get; set; }

        /// <summary>
        /// Replies to the message .
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="replyMessage">The reply message.</param>
        void Reply<T>(T replyMessage);

        /// <summary>
        /// Gets or sets the action to execute upon message reply.
        /// </summary>
        /// <value>The on reply.</value>
        Action<object, IMessageContext> OnReply { get; set; }

        /// <summary>
        /// Gets or sets an identifier that uniquely identifies a request/reply exchange.
        /// </summary>
        /// <value>The request identifier.</value>
        Guid RequestIdentifier { get; set; }

        /// <summary>
        /// Gets or sets the intended MessagingChannel.
        /// </summary>
        /// <value>The MessagingChannel.</value>
        IMessagingChannel MessagingChannel { get; set; }
    }

    /// <summary>
    /// Context delivered with a message that allows contact to the bus that delivered the message and 
    /// allows acknowledgement of the message or replies to request type messages.
    /// </summary>
    public class MessageContext : IMessageContext
    {
        /// <summary>
        /// Gets or sets the bus this message was delivered from.
        /// </summary>
        /// <value>The bus.</value>
        public IServiceBus Bus { get; set; }

        /// <summary>
        /// Gets or sets the number of times the message has been attempted to be delivered.
        /// </summary>
        /// <value>The number of delivery attempts.</value>
        public int NumberOfDeliveryAttempts { get; set; }

        /// <summary>
        /// Gets or sets the raw message.
        /// </summary>
        /// <value>The raw message.</value>
        public object RawMessage { get; set; }

        /// <summary>
        /// Gets or sets the id of the workflow instance orchestrating the business process the message is participating in.
        /// </summary>
        /// <value>The workflow instance id.</value>
        public Guid WorkflowInstanceId { get; set; }

        /// <summary>
        /// Replies to the message .
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="replyMessage">The reply message.</param>
        public void Reply<T>(T replyMessage)
        {
            if(OnReply != null)
                OnReply.Invoke(replyMessage, this);
        }

        /// <summary>
        /// Gets or sets the action to execute upon message reply.
        /// </summary>
        /// <value>The on reply.</value>
        public Action<object, IMessageContext> OnReply { get; set; }

        /// <summary>
        /// Gets or sets an identifier that uniquely identifies a request/reply exchange.
        /// </summary>
        /// <value>The request identifier.</value>
        public Guid RequestIdentifier { get; set; }

        /// <summary>
        /// Gets or sets the intended MessagingChannel.
        /// </summary>
        /// <value>The MessagingChannel.</value>
        public IMessagingChannel MessagingChannel { get; set; }
    }
}
